package com.shitou.shitoumember.service.impl;

import com.alibaba.fastjson.JSON;
import com.shitou.shitoucommons.utils.*;
import com.shitou.shitoumember.entity.MemberEntity;
import com.shitou.shitoumember.service.MemberService;
import com.shitou.shitoumember.utils.RespBeanMenu;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.shitou.shitoumember.dao.TokenDao;
import com.shitou.shitoumember.entity.TokenEntity;
import com.shitou.shitoumember.service.TokenService;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

@Slf4j
@Transactional
@Service("tokenService")
public class TokenServiceImpl extends ServiceImpl<TokenDao, TokenEntity> implements TokenService {

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<TokenEntity> page = this.page(
                new Query<TokenEntity>().getPage(params),
                new QueryWrapper<TokenEntity>()
        );

        return new PageUtils(page);
    }

    @Autowired
    @Qualifier("RedisTemplate")
    private RedisTemplate redisTemplate;

    @Autowired
    private MemberService memberService;


    /**
     * @param memberId
     * @return
     */
    @Override
    public RespBean createToken(long memberId) {
        // 如果之前登陆过了，那么删除之前的数据
        TokenEntity tokenEntity = this.getOne(new QueryWrapper<TokenEntity>().eq("member_id", memberId));
        if ( tokenEntity != null ){
            String token1 = tokenEntity.getToken();
            if ( token1 != null && !token1.equals("")){
                redisTemplate.delete("member:" + token1);
            }
        }

        // 生成token
        String token = TokenGenerator.generatorValue();
        // 查看是否已经拥有token了
        TokenEntity tokenDo = this.getOne(new QueryWrapper<TokenEntity>().eq("member_id", memberId));
        if ( tokenDo == null ){
            tokenDo = new TokenEntity();
            // 为空，第一次登录
            tokenDo.setToken(token);
            // 设置半个小时
            tokenDo.setExpireTime(DateUtils.addDateMinutes(new Date(), 32));
            tokenDo.setMemberId(memberId);
            tokenDo.setUpdateTime(new Date());
            baseMapper.insert(tokenDo);
        }else {
            // 已经登陆过了，更新
            tokenDo.setUpdateTime(new Date());
            tokenDo.setExpireTime(DateUtils.addDateMinutes(new Date(), 32));
            tokenDo.setMemberId(memberId);
            tokenDo.setToken(token);
            // 更新
            baseMapper.updateById(tokenDo);
        }

        return RespBean.success().put("token", token).put("expireTime", 60*32);
    }

    /**
     * 登出
     * @param memberId
     * @return
     */
    @Override
    public RespBean loginOut(long memberId) {
        // 生成token
        String token = TokenGenerator.generatorValue();
        // 修改token
        TokenEntity tokenDo = this.getOne(new QueryWrapper<TokenEntity>().eq("member_id", memberId));
        String oldToken = tokenDo.getToken();
        tokenDo.setToken(token);
        tokenDo.setMemberId(memberId);
        Date date = new Date();
        tokenDo.setUpdateTime(date);
        tokenDo.setExpireTime(date);

        redisTemplate.delete("member:" + oldToken);
        baseMapper.updateById(tokenDo);
        return RespBean.success();
    }

    /**
     * 判断是否登录
     * @param token
     * @return
     */
    @Override
    public TokenEntity checkTokenTime(String token, HttpServletResponse response) {
        return checkTokenTime(token, false, response);
    }

    /**
     * 验证登录
     * @param token token
     * @param forceLogin 判断前台，如果为true，则访问该页面时
     *                   如果没有登陆，强制用户前往用户界面进行登录，
     * @return
     */
    public TokenEntity checkTokenTime(String token, boolean forceLogin, HttpServletResponse response){
        int code = forceLogin? RespBeanMenu.NO_LOGIN_FORCE.getCode() :  RespBeanMenu.NO_LOGIN.getCode();
        // 查询
        TokenEntity umsToken = this.getOne(new QueryWrapper<TokenEntity>().eq("token", token));
        if ( umsToken == null ){
            return null;
        }
        // 判断时间
        if ( new Date().getTime() > umsToken.getExpireTime().getTime()  ){
            return null;
        }

        if ( response != null ){
            // 从新设置登陆时长两年半
            Cookie cookie = new Cookie("memberTicket", token);
            cookie.setPath("/");
            cookie.setMaxAge(60 * 32);
            response.addCookie(cookie);

            MemberEntity id = memberService.getOne(new QueryWrapper<MemberEntity>().eq("id", umsToken.getMemberId()));
            String jsonString = (String) JSON.toJSONString(id);
            redisTemplate.opsForValue().set("member:" + token, jsonString, 60 * 30, TimeUnit.SECONDS);
        }
        //登录验证成功
        return umsToken;
    }

}
